package org.etlt.expression.function;

import org.apache.commons.lang3.time.DateFormatUtils;
import org.apache.commons.lang3.time.DateUtils;

import java.math.BigDecimal;
import java.sql.Timestamp;
import java.util.Date;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * system default functions for Math
 * @version 2.0
 */
public class MathFunctions {

    private AtomicInteger sequence ;

    @FunctionEnabled(value = "abs", help = "get absolute value of the input number")
    public Object abs(String input){
        return Math.abs(Double.valueOf(input).doubleValue());
    }

    @FunctionEnabled(value = "add", help = "add all of the input numbers")
    public Object add(Object ... inputs){
        if(inputs.length < 2)
            throw new IllegalArgumentException("the input number must be at least 2.");
        BigDecimal result = new BigDecimal(0);
        for(int i = 0; i < inputs.length; i++){
            if(inputs[i] != null)
                result = result.add(new BigDecimal(String.valueOf(inputs[i])));
        }
        return result;
    }

    @FunctionEnabled(value = "addMixed", help = "add all of the input Object")
    public Object addMixed(Object ... inputs){
        if(inputs.length < 2)
            throw new IllegalArgumentException("the input number must be at least 2.");
        BigDecimal result = new BigDecimal(0);
        for(int i = 0; i < inputs.length; i++){
            Object input = inputs[i];
            if(input instanceof Date){
                Date ts = (Date) input;
                String dateAsString = DateFormatUtils.format(ts, "yyyyMMddHHmmss");
                result = result.add(new BigDecimal(dateAsString));
            }else if(input != null)
                result = result.add(new BigDecimal(String.valueOf(inputs[i])));
        }
        return result;
    }

    @FunctionEnabled(value = "seq", help = "get sequence from the given argument")
    public int sequence(int from){
        synchronized (this) {
            if (this.sequence == null) {
                this.sequence = new AtomicInteger(from);
            }
        }
        return this.sequence.getAndIncrement();
    }
}
